package com.vincent.template.service.logic.impl;

import com.vincent.template.commons.exception.Vct520Exception;
import com.vincent.template.domain.SysBindAuthGroupAuthPo;
import com.vincent.template.domain.SysBindAuthGroupRolePo;
import com.vincent.template.domain.SysBindAuthUriPo;
import com.vincent.template.domain.SysBindRoleAuthPo;
import com.vincent.template.domain.SysBindUserGroupRolePo;
import com.vincent.template.domain.SysBindUserGroupUserPo;
import com.vincent.template.domain.SysBindUserRolePo;
import com.vincent.template.dto.sys.bind.BindAuthGroupAuthDto;
import com.vincent.template.dto.sys.bind.BindAuthUriDto;
import com.vincent.template.dto.sys.bind.BindRoleAuthDto;
import com.vincent.template.dto.sys.bind.BindRoleAuthGroupDto;
import com.vincent.template.dto.sys.bind.BindUserGroupRoleDto;
import com.vincent.template.dto.sys.bind.BindUserGroupUserDto;
import com.vincent.template.dto.sys.bind.BindUserRoleDto;
import com.vincent.template.repository.SysAuthGroupRepository;
import com.vincent.template.repository.SysAuthRepository;
import com.vincent.template.repository.SysBindAuthGroupAuthRepository;
import com.vincent.template.repository.SysBindAuthGroupRoleRepository;
import com.vincent.template.repository.SysBindAuthUriRepository;
import com.vincent.template.repository.SysBindRoleAuthRepository;
import com.vincent.template.repository.SysBindUserGroupRoleRepository;
import com.vincent.template.repository.SysBindUserGroupUserRepository;
import com.vincent.template.repository.SysBindUserRoleRepository;
import com.vincent.template.repository.SysRoleRepository;
import com.vincent.template.repository.SysUriRepository;
import com.vincent.template.repository.SysUserGroupRepository;
import com.vincent.template.repository.SysUserRepository;
import com.vincent.template.service.logic.BindService;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Vincent Wang
 * @date 2021/3/25 22:03
 */
@Service
public class BindServiceImpl implements BindService {

    @Autowired
    private SysUserRepository userRepository;
    @Autowired
    private SysUserGroupRepository userGroupRepository;
    @Autowired
    private SysRoleRepository roleRepository;
    @Autowired
    private SysAuthRepository authRepository;
    @Autowired
    private SysAuthGroupRepository authGroupRepository;
    @Autowired
    private SysUriRepository uriRepository;
    @Autowired
    private SysBindUserGroupUserRepository bindUserGroupUserRepository;
    @Autowired
    private SysBindUserRoleRepository bindUserRoleRepository;
    @Autowired
    private SysBindUserGroupRoleRepository bindUserGroupRoleRepository;
    @Autowired
    private SysBindRoleAuthRepository bindRoleAuthRepository;
    @Autowired
    private SysBindAuthGroupRoleRepository bindAuthGroupRoleRepository;
    @Autowired
    private SysBindAuthGroupAuthRepository bindAuthGroupAuthRepository;
    @Autowired
    private SysBindAuthUriRepository bindAuthUriRepository;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean bindUserGroupUser(BindUserGroupUserDto dto, boolean unbind) {
        Long userGroupId = dto.getUserGroupId();
        Vct520Exception.throwIfTrue(!userGroupRepository.existsById(userGroupId),
                "该用户组id不存在：" + userGroupId);
        List<String> userIds = dto.getUserIds();
        List<String> illegalUserIds = userRepository.findNotExistingIds(userIds);
        Vct520Exception.throwIfTrue(CollectionUtils.isNotEmpty(illegalUserIds),
                "用户id不存在：" + illegalUserIds);
        List<SysBindUserGroupUserPo> existingBindings = bindUserGroupUserRepository
                .findByUserGroupIdAndUserIdIn(userGroupId, userIds);
        if (unbind) {
            if (CollectionUtils.isNotEmpty(existingBindings)) {
                bindUserGroupUserRepository.deleteInBatch(existingBindings);
            }
            return true;
        }
        List<String> existingUserIds = existingBindings.stream()
                .map(SysBindUserGroupUserPo::getUserId).collect(Collectors.toList());
        List<SysBindUserGroupUserPo> addBindings = userIds.stream()
                .filter(userId -> !existingUserIds.contains(userId))
                .map(userId -> new SysBindUserGroupUserPo(userGroupId, userId))
                .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(addBindings)) {
            bindUserGroupUserRepository.saveAll(addBindings);
        }
        return true;
    }

    @Override
    public boolean bindUserRole(BindUserRoleDto dto, boolean unbind) {
        String userId = dto.getUserId();
        Vct520Exception.throwIfTrue(!userRepository.existsById(userId),
                "该用户id不存在：" + userId);
        List<Long> roleIds = dto.getRoleIds();
        List<Long> illegalRoleIds = roleRepository.findNotExistingIds(roleIds);
        Vct520Exception.throwIfTrue(CollectionUtils.isNotEmpty(illegalRoleIds),
                "角色id不存在：" + illegalRoleIds);
        List<SysBindUserRolePo> existingBindings = bindUserRoleRepository
                .findByUserIdAndRoleIdIn(userId, roleIds);
        if (unbind) {
            if (CollectionUtils.isNotEmpty(existingBindings)) {
                bindUserRoleRepository.deleteInBatch(existingBindings);
            }
            return true;
        }
        List<Long> existingRoleIds = existingBindings.stream()
                .map(SysBindUserRolePo::getRoleId).collect(Collectors.toList());
        List<SysBindUserRolePo> addBindings = roleIds.stream()
                .filter(roleId -> !existingRoleIds.contains(roleId))
                .map(roleId -> new SysBindUserRolePo(userId, roleId))
                .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(addBindings)) {
            bindUserRoleRepository.saveAll(addBindings);
        }
        return true;
    }

    @Override
    public boolean bindUserGroupRole(BindUserGroupRoleDto dto, boolean unbind) {
        Long userGroupId = dto.getUserGroupId();
        Vct520Exception.throwIfTrue(!userGroupRepository.existsById(userGroupId),
                "该用户组id不存在：" + userGroupId);
        List<Long> roleIds = dto.getRoleIds();
        List<Long> illegalRoleIds = roleRepository.findNotExistingIds(roleIds);
        Vct520Exception.throwIfTrue(CollectionUtils.isNotEmpty(illegalRoleIds),
                "角色id不存在：" + illegalRoleIds);
        List<SysBindUserGroupRolePo> existingBindings = bindUserGroupRoleRepository
                .findByUserGroupIdAndRoleIdIn(userGroupId, roleIds);
        if (unbind) {
            if (CollectionUtils.isNotEmpty(existingBindings)) {
                bindUserGroupRoleRepository.deleteInBatch(existingBindings);
            }
            return true;
        }
        List<Long> existingRoleIds = existingBindings.stream()
                .map(SysBindUserGroupRolePo::getRoleId).collect(Collectors.toList());
        List<SysBindUserGroupRolePo> addBindings = roleIds.stream()
                .filter(roleId -> !existingRoleIds.contains(roleId))
                .map(roleId -> new SysBindUserGroupRolePo(userGroupId, roleId))
                .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(addBindings)) {
            bindUserGroupRoleRepository.saveAll(addBindings);
        }
        return true;
    }

    @Override
    public boolean bindRoleAuth(BindRoleAuthDto dto, boolean unbind) {
        Long roleId = dto.getRoleId();
        Vct520Exception.throwIfTrue(!roleRepository.existsById(roleId),
                "该角色id不存在：" + roleId);
        List<Long> authIds = dto.getAuthIds();
        List<Long> illegalAuthIds = authRepository.findNotExistingIds(authIds);
        Vct520Exception.throwIfTrue(CollectionUtils.isNotEmpty(illegalAuthIds),
                "权限id不存在：" + illegalAuthIds);
        List<SysBindRoleAuthPo> existingBindings = bindRoleAuthRepository
                .findByRoleIdAndAuthIdIn(roleId, authIds);
        if (unbind) {
            if (CollectionUtils.isNotEmpty(existingBindings)) {
                bindRoleAuthRepository.deleteInBatch(existingBindings);
            }
            return true;
        }
        List<Long> existingAuthIds = existingBindings.stream()
                .map(SysBindRoleAuthPo::getAuthId).collect(Collectors.toList());
        List<SysBindRoleAuthPo> addBindings = authIds.stream()
                .filter(authId -> !existingAuthIds.contains(authId))
                .map(authId -> new SysBindRoleAuthPo(roleId, authId))
                .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(addBindings)) {
            bindRoleAuthRepository.saveAll(addBindings);
        }
        return true;
    }

    @Override
    public boolean bindRoleAuthGroup(BindRoleAuthGroupDto dto, boolean unbind) {
        Long roleId = dto.getRoleId();
        Vct520Exception.throwIfTrue(!roleRepository.existsById(roleId),
                "该角色id不存在：" + roleId);
        List<Long> authGroupIds = dto.getAuthGroupIds();
        List<Long> illegalAuthGroupIds = authGroupRepository.findNotExistingIds(authGroupIds);
        Vct520Exception.throwIfTrue(CollectionUtils.isNotEmpty(illegalAuthGroupIds),
                "权限组id不存在：" + illegalAuthGroupIds);
        List<SysBindAuthGroupRolePo> existingBindings = bindAuthGroupRoleRepository
                .findByAuthGroupIdInAndRoleId(authGroupIds, roleId);
        if (unbind) {
            if (CollectionUtils.isNotEmpty(existingBindings)) {
                bindAuthGroupRoleRepository.deleteInBatch(existingBindings);
            }
            return true;
        }
        List<Long> existingAuthGroupIds = existingBindings.stream()
                .map(SysBindAuthGroupRolePo::getAuthGroupId).collect(Collectors.toList());
        List<SysBindAuthGroupRolePo> addBindings = authGroupIds.stream()
                .filter(authGroupId -> !existingAuthGroupIds.contains(authGroupId))
                .map(authGroupId -> new SysBindAuthGroupRolePo(authGroupId, roleId))
                .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(addBindings)) {
            bindAuthGroupRoleRepository.saveAll(addBindings);
        }
        return true;
    }

    @Override
    public boolean bindAuthGroupAuth(BindAuthGroupAuthDto dto, boolean unbind) {
        Long authGroupId = dto.getAuthGroupId();
        Vct520Exception.throwIfTrue(!authGroupRepository.existsById(authGroupId),
                "该权限组id不存在：" + authGroupId);
        List<Long> authIds = dto.getAuthIds();
        List<Long> illegalAuthIds = authRepository.findNotExistingIds(authIds);
        Vct520Exception.throwIfTrue(CollectionUtils.isNotEmpty(illegalAuthIds),
                "权限id不存在：" + illegalAuthIds);
        List<SysBindAuthGroupAuthPo> existingBindings = bindAuthGroupAuthRepository
                .findByAuthGroupIdAndAuthIdIn(authGroupId, authIds);
        if (unbind) {
            if (CollectionUtils.isNotEmpty(existingBindings)) {
                bindAuthGroupAuthRepository.deleteInBatch(existingBindings);
            }
            return true;
        }
        List<Long> existingAuthIds = existingBindings.stream()
                .map(SysBindAuthGroupAuthPo::getAuthId).collect(Collectors.toList());
        List<SysBindAuthGroupAuthPo> addBindings = authIds.stream()
                .filter(authId -> !existingAuthIds.contains(authId))
                .map(authId -> new SysBindAuthGroupAuthPo(authGroupId, authId))
                .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(addBindings)) {
            bindAuthGroupAuthRepository.saveAll(addBindings);
        }
        return true;
    }

    @Override
    public boolean bindAuthUri(BindAuthUriDto dto, boolean unbind) {
        Long authId = dto.getAuthId();
        Vct520Exception.throwIfTrue(!authRepository.existsById(authId),
                "该权限id不存在：" + authId);
        List<Long> uriIds = dto.getUriIds();
        List<Long> illegalUriIds = uriRepository.findNotExistingIds(uriIds);
        Vct520Exception.throwIfTrue(CollectionUtils.isNotEmpty(illegalUriIds),
                "uri资源id不存在：" + illegalUriIds);
        List<SysBindAuthUriPo> existingBindings = bindAuthUriRepository
                .findByAuthIdAndUriIdIn(authId, uriIds);
        if (unbind) {
            if (CollectionUtils.isNotEmpty(existingBindings)) {
                bindAuthUriRepository.deleteInBatch(existingBindings);
            }
            return true;
        }
        List<Long> existingUriIds = existingBindings.stream()
                .map(SysBindAuthUriPo::getUriId).collect(Collectors.toList());
        List<SysBindAuthUriPo> addBindings = uriIds.stream()
                .filter(uriId -> !existingUriIds.contains(uriId))
                .map(uriId -> new SysBindAuthUriPo(authId, uriId))
                .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(addBindings)) {
            bindAuthUriRepository.saveAll(addBindings);
        }
        return true;
    }
}
